<script lang="ts" setup>
import { ref, watch, onMounted, computed } from "vue";
import type { PartInfo } from "./maintenance/part-info";
import { lubricationParts as defaultLubricationParts } from "./maintenance/lubrication-parts";
import { tightenParts as defaultTightenParts } from "./maintenance/tighten-parts";
import type { MaintenanceInfo } from "./maintenance/maintenance-info";
import { useRoute } from "vue-router";
import { String } from "@/utils/string";
import { HttpClient } from "@/utils/http-client";
import type { DeviceMaintenanceResponse } from "./types/device-maintenance-response";
import type { DevicePartResponse } from "./types/device-part-response";
import { UserFriendlyException } from "@/exceptions/IUserFriendlyException";
import { maintenanceInfos as defaultMaintenanceInfos } from "./maintenance/maintenance-infos";
import { MaintenanceStatus } from "./types/maintenance-status";
import { ElMessage, ElMessageBox } from "element-plus";
import { MaintenanceStep } from "./types/maintenance-step";
import type { MaintenanceRecordResponse } from "./types/maintenance-record-response";
import { DateConverter } from "@/utils/date-converter";
import type { DevicePartCheckedResultResponse } from "./types/device-part-checked-result-response";
import type { CheckInfo } from "./maintenance/check-info";
import type { DevicePartCheckItemResponse } from "./types/device-part-check-item-response";
import { useRouter } from "vue-router";

const router = useRouter();
const lubricationParts = ref<PartInfo[]>(defaultLubricationParts);
const tightenParts = ref<PartInfo[]>(defaultTightenParts);
const maintenanceInfos = ref<MaintenanceInfo[]>(defaultMaintenanceInfos);
const isShowCheckListDialog = ref(false);

const baseUrl = import.meta.env.VITE_DEVICE_OPS_SERVICE_BASE_URL;
const httpClient = new HttpClient();

const route = useRoute();
// 设备资源号
const resourceId = ref("");

const deviceId = ref("");

// 当前部件名称
const currentPartName = ref("");
// 显示步骤
const isShowSteps = ref(false);
// 设备维护状态
const maintenanceStatus = ref("");
const isLoading = ref(false);
// 部件正在维护
const isUnderMaintenance = ref(false);
const isRuning = computed(() => {
  return !isUnderMaintenance.value;
});

// 当前部件 id
const currentPartId = ref("");
const currentRecordStep = ref(-1);
const notRevertStep = computed(() => {
  return (isUnderMaintenance.value && currentRecordStep.value <= 0) || isRuning.value;
});
const notNextStep = computed(() => {
  return (isUnderMaintenance.value && currentRecordStep.value >= 6) || isRuning.value;
});

// 最后一次搅拌轴保养时间
const lastMixingRecordTime = ref("无记录");
// 最后一个分散周保养时间
const lastLubricationRecordTime = ref("无记录");

// 当前记录 id
const currentRecordId = ref("");
// 校验清单列表
const checkedItemList = ref<CheckInfo[]>([]);

onMounted(async () => {
  const id = route.query.deviceId as string;

  if (id !== null && !String.isNullOrWhitespace(id)) {
    deviceId.value = decodeURIComponent(id);
    try {
      isLoading.value = true;
      const deviceParts = await getDevicePartsAsync(id);
      updateMaintenanceInfos(deviceParts);
      updateMixingLastMaintenanceDateAsync();
    } catch (err) {
      if (err instanceof UserFriendlyException) {
        ElMessageBox.alert(err.message);
      } else {
        ElMessageBox.alert("加载数据错误！");
      }
    } finally {
      isLoading.value = false;
    }
  }
});

function updateMaintenanceInfos(parts: DevicePartResponse[]) {
  parts.forEach((partItem) => {
    if (partItem.devicePartName === "搅拌轴承") {
      const info = maintenanceInfos.value[0];
      info.id = partItem.id;
      info.accumulatedDowntime = partItem.accumulatedDowntime;
      info.economicLifetimeThreshold = partItem.economicLifetimeThreshold;
      info.currentLifetime = partItem.currentLifetime;
      info.residualLifetime = partItem.accumulatedDowntime - partItem.currentLifetime;
    } else if (partItem.devicePartName === "分散轴承") {
      const info = maintenanceInfos.value[1];
      info.id = partItem.id;
      info.accumulatedDowntime = partItem.accumulatedDowntime;
      info.economicLifetimeThreshold = partItem.economicLifetimeThreshold;
      info.currentLifetime = partItem.currentLifetime;
      info.residualLifetime = partItem.accumulatedDowntime - partItem.currentLifetime;
    }
  });

  parts.forEach((partItem) => {
    for (let i = 0; i < lubricationParts.value.length; i++) {
      const item = lubricationParts.value[i];
      if (item.partName === partItem.devicePartName) {
        item.id = partItem.id;
        item.accumulatedDowntime = partItem.accumulatedDowntime;
        item.economicLifetimeThreshold = partItem.economicLifetimeThreshold;
        item.currentLifetime = partItem.currentLifetime;
        item.residualLifetime = partItem.accumulatedDowntime - partItem.currentLifetime;
      }
    }
  });
}

watch(currentPartName, (value: string) => {
  if (String.isNullOrWhitespace(value)) {
    isShowSteps.value = false;
  } else {
    isShowSteps.value = true;
  }
});

const onRowDoubleClick = (row: unknown) => {
  const idDesc = Object.getOwnPropertyDescriptor(row, "id");
  const partNameDesc = Object.getOwnPropertyDescriptor(row, "partName");
  const stringPartName = partNameDesc?.value as string;
  const idString = idDesc?.value as string;
  if (
    idString !== null &&
    stringPartName !== null &&
    !String.isNullOrEmpty(idString) &&
    !String.isNullOrEmpty(stringPartName)
  ) {
    currentPartName.value = stringPartName;
    isShowSteps.value = true;
    currentPartId.value = idString;
    try {
      updateCurrentPartMaintenanceInfoAsync(idString);
    } catch (err) {
      if (err instanceof UserFriendlyException) {
        ElMessageBox.alert(err.message);
      } else {
        ElMessageBox.alert("更新维护信息错误！");
      }
    }
  } else {
    isShowSteps.value = false;
    ElMessage.info("未添加该部件，请联系管理员添加！");
  }
};

// 更新当前部件维护信息
async function updateCurrentPartMaintenanceInfoAsync(id: string) {
  currentRecordId.value = "";
  currentRecordStep.value = -1;
  const part = await httpClient.getAsync<DevicePartResponse>(baseUrl + "/device-parts/" + id);
  const status = MaintenanceStatus.getStatus(part.maintenanceStatus);
  maintenanceStatus.value = status;
  isUnderMaintenance.value = part.maintenanceStatus === "UnderMaintenance";
  checkedItemList.value = [];

  if (isUnderMaintenance.value) {
    const record = await httpClient.getAsync<MaintenanceRecordResponse>(
      baseUrl + "/device-parts/" + part.id + "/active-record"
    );

    currentRecordId.value = record.id;
    updateCheckedItemsAsync(record.id);

    if (record.maintenanceStep !== undefined) {
      currentRecordStep.value = MaintenanceStep.getIndex(record.maintenanceStep);
    }
  }
}

async function getDevicePartsAsync(deviceId: string) {
  const maintenance = await httpClient.getAsync<DeviceMaintenanceResponse>(
    baseUrl + "/device-maintenances/" + deviceId
  );

  resourceId.value = maintenance.deviceName;

  const parts = await httpClient.getAsync<DevicePartResponse[]>(
    baseUrl + "/device-maintenances/" + maintenance.id + "/parts"
  );

  return parts;
}

// 开始维护部件
const startMaintaining = async (id: string) => {
  ElMessageBox.confirm("您确定要开始维护该部件吗?", "警告", {
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    type: "warning"
  }).then(async () => {
    isLoading.value = true;
    try {
      await httpClient.actionAsync(baseUrl + "/device-parts/" + id + "/start-maintaining", {});
      await updateCurrentPartMaintenanceInfoAsync(id);
      currentRecordStep.value = 0;
      ElMessage.info("开始维护部件 " + currentPartName.value);
    } catch (err) {
      if (err instanceof UserFriendlyException) {
        ElMessageBox.alert(err.message);
      } else {
        ElMessageBox.alert("服务器错误！");
        console.error(err);
      }
    } finally {
      isLoading.value = false;
    }
  });
};

// 开始维护部件
const cancelMaintaining = async (id: string) => {
  ElMessageBox.prompt("请输入终止维护原因", "提示", {
    confirmButtonText: "确定",
    cancelButtonText: "返回"
  }).then(async ({ value }) => {
    isLoading.value = true;
    try {
      await httpClient.actionAsync(baseUrl + "/device-parts/" + id + "/cancel-maintaining", {
        reason: value
      });
      await updateCurrentPartMaintenanceInfoAsync(id);
      ElMessage.info("终止维护部件 " + currentPartName.value);
    } catch (err) {
      if (err instanceof UserFriendlyException) {
        ElMessageBox.alert(err.message);
      } else {
        ElMessageBox.alert("服务器错误！");
        console.error(err);
      }
    } finally {
      isLoading.value = false;
    }
  });
};

// 开始维护部件
async function endMaintainingAsync(id: string) {
  isLoading.value = true;
  try {
    await httpClient.actionAsync(baseUrl + "/device-parts/" + id + "/end-maintaining", {});
    await updateCurrentPartMaintenanceInfoAsync(id);
    currentRecordStep.value = -1;
    ElMessage.info("完成保养部件 " + currentPartName.value);
  } catch (err) {
    if (err instanceof UserFriendlyException) {
      ElMessageBox.alert(err.message);
    } else {
      ElMessageBox.alert("服务器错误！");
      console.error(err);
    }
  } finally {
    isLoading.value = false;
  }
}

const revertStep = async (id: string) => {
  ElMessageBox.confirm("您确定要执行到上一个步骤吗?", "警告", {
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    type: "warning"
  }).then(async () => {
    isLoading.value = true;
    try {
      await httpClient.actionAsync(baseUrl + "/device-parts/" + id + "/maintenance-step", {
        action: 1
      });
      await updateCurrentPartMaintenanceInfoAsync(id);
    } catch (err) {
      if (err instanceof UserFriendlyException) {
        ElMessageBox.alert(err.message);
      } else {
        ElMessageBox.alert("服务器错误！");
        console.error(err);
      }
    } finally {
      isLoading.value = false;
    }
  });
};

const nextStep = async (id: string) => {
  if (currentRecordStep.value >= 5) {
    ElMessageBox.confirm("您确定要完工一个部件保养吗?", "警告", {
      confirmButtonText: "确定",
      cancelButtonText: "取消",
      type: "warning"
    }).then(async () => {
      await endMaintainingAsync(id);
    });
  } else {
    ElMessageBox.confirm("您确定要执行到下一个步骤吗?", "警告", {
      confirmButtonText: "确定",
      cancelButtonText: "取消",
      type: "warning"
    }).then(async () => {
      isLoading.value = true;
      try {
        await httpClient.actionAsync(baseUrl + "/device-parts/" + id + "/maintenance-step", {
          action: 0
        });
        await updateCurrentPartMaintenanceInfoAsync(id);
      } catch (err) {
        if (err instanceof UserFriendlyException) {
          ElMessageBox.alert(err.message);
        } else {
          ElMessageBox.alert("服务器错误！");
          console.error(err);
        }
      } finally {
        isLoading.value = false;
      }
    });
  }
};

async function getLastRecordDateAsync(partId: string) {
  const record = await httpClient.getAsync<MaintenanceRecordResponse | null>(
    baseUrl + "/device-parts/" + partId + "/last-record"
  );

  if (record == null) {
    return "无记录";
  }

  return DateConverter.toShangHaiTime(record.creationTime);
}

// 更新维护的日期
async function updateMixingLastMaintenanceDateAsync() {
  let id = maintenanceInfos.value[0].id;
  if (!String.isNullOrWhitespace(id)) {
    lastMixingRecordTime.value = await getLastRecordDateAsync(id!);
    maintenanceInfos.value[0].lasteMaintenanceTime = lastMixingRecordTime.value;
  }
  id = maintenanceInfos.value[1].id;
  if (!String.isNullOrWhitespace(id)) {
    lastLubricationRecordTime.value = await getLastRecordDateAsync(id!);
    maintenanceInfos.value[1].lasteMaintenanceTime = lastLubricationRecordTime.value;
  }

  lubricationParts.value.forEach(async (item) => {
    if (!String.isNullOrWhitespace(item.id)) {
      item.lasteMaintenanceTime = await getLastRecordDateAsync(item.id!);
    } else {
      item.lasteMaintenanceTime = "无";
    }
  });

  tightenParts.value.forEach(async (item) => {
    if (!String.isNullOrWhitespace(item.id)) {
      item.lasteMaintenanceTime = await getLastRecordDateAsync(item.id!);
    } else {
      item.lasteMaintenanceTime = "无";
    }
  });
}

async function updateCheckedItemsAsync(recordId: string) {
  checkedItemList.value = [];
  const checkedItems = await httpClient.getAsync<DevicePartCheckedResultResponse[]>(
    baseUrl + "/maintenance-records/" + recordId + "/checked-results"
  );

  checkedItems.forEach(async (item) => {
    const checkItem = await httpClient.getAsync<DevicePartCheckItemResponse>(
      baseUrl + "/device-part-check-items/" + item.checkItemId
    );

    checkedItemList.value.push({
      description: checkItem.description,
      checkedItemId: item.id,
      isPassed: item.isPassed,
      result: item.isPassed ? "已校验" : "未校验"
    });
  });
}

const onPassClick = async (row: CheckInfo) => {
  ElMessageBox.confirm("请仔细核对需要校验的内容是否已经校验完成?", "警告", {
    confirmButtonText: "确认无误且通过校验",
    cancelButtonText: "我在仔细核对一下",
    type: "warning"
  }).then(async () => {
    isLoading.value = true;
    try {
      await httpClient.actionAsync(
        baseUrl + "/device-part-checked-results/" + row.checkedItemId + "/pass",
        {}
      );

      if (!String.isNullOrWhitespace(currentRecordId.value))
        await updateCheckedItemsAsync(currentRecordId.value);
    } catch (err) {
      if (err instanceof UserFriendlyException) {
        ElMessageBox.alert(err.message);
      } else {
        ElMessageBox.alert("服务器错误！");
        console.error(err);
      }
    } finally {
      isLoading.value = false;
    }
  });
};

const onFailClick = async (row: CheckInfo) => {
  ElMessageBox.confirm("撤销后需要重新校验，你确定要撤销吗?", "警告", {
    confirmButtonText: "我确定要重新校验",
    cancelButtonText: "取消",
    type: "warning"
  }).then(async () => {
    isLoading.value = true;
    try {
      await httpClient.actionAsync(
        baseUrl + "/device-part-checked-results/" + row.checkedItemId + "/fail",
        {}
      );

      if (!String.isNullOrWhitespace(currentRecordId.value))
        await updateCheckedItemsAsync(currentRecordId.value);
    } catch (err) {
      if (err instanceof UserFriendlyException) {
        ElMessageBox.alert(err.message);
      } else {
        ElMessageBox.alert("服务器错误！");
        console.error(err);
      }
    } finally {
      isLoading.value = false;
    }
  });
};

const onBack = () => {
  router.go(-1);
};

const cardboardUrl = computed(() => {
  return "/cardboards/mixing?deviceId=" + deviceId.value;
});
</script>

<template>
  <div class="main-container" v-loading="isLoading">
    <div class="content-container">
      <div class="device-card">
        <div class="card-header">
          <span>设备资源号：{{ resourceId }}</span>
          <router-link :to="cardboardUrl">
            <span style="margin-left: 16px">设备看板</span>
          </router-link>
        </div>
        <div class="card-body">
          <img src="@/assets/images/mixing-machine-2d.png" width="300px" />
        </div>
        <div class="card-footer">
          <div>
            <span>搅拌-上次保养：{{ lastMixingRecordTime }}</span>
          </div>
          <div>
            <span>分散-上次保养：{{ lastLubricationRecordTime }}</span>
          </div>
          <div class="space-between">
            <span style="color: #cc489e; text-align: center; display: block">
              双击表行查看设备维护状态
            </span>
            <el-button
              @click="isShowCheckListDialog = true"
              :disabled="!isUnderMaintenance"
              style="width: 88px"
              type="primary"
              >校验清单</el-button
            >
          </div>
        </div>
      </div>
      <div class="table-container">
        <el-table
          header-cell-class-name="first-table-header-cell-class-name"
          :data="maintenanceInfos"
          border
          style="width: 1000px; margin-left: 8px"
          @row-dblclick="onRowDoubleClick"
        >
          <el-table-column prop="partName" label="类别" width="180" />
          <el-table-column prop="accumulatedDowntime" label="保养时间间隔" />
          <el-table-column prop="economicLifetimeThreshold" label="预警间隔" />
          <el-table-column prop="currentLifetime" label="当前运行时间" />
          <el-table-column prop="residualLifetime" label="距离下次保养" />
          <el-table-column prop="lasteMaintenanceTime" label="最后一次保养时间" width="200" />
        </el-table>
        <el-table
          header-cell-class-name="second-table-header-cell-class-name"
          :data="lubricationParts"
          border
          style="width: 1000px; margin-left: 8px; margin-top: 8px"
          @row-dblclick="onRowDoubleClick"
        >
          <el-table-column prop="partName" label="润滑部位" width="180" />
          <el-table-column prop="accumulatedDowntime" label="保养时间间隔" />
          <el-table-column prop="economicLifetimeThreshold" label="预警间隔" />
          <el-table-column prop="currentLifetime" label="当前运行时间" />
          <el-table-column prop="residualLifetime" label="距离下次保养" />
          <el-table-column prop="lasteMaintenanceTime" label="最后一次保养时间" width="200" />
        </el-table>
        <el-table
          header-cell-class-name="third-table-header-cell-class-name"
          :data="tightenParts"
          border
          style="width: 1000px; margin-left: 8px; margin-top: 8px"
          @row-dblclick="onRowDoubleClick"
        >
          <el-table-column prop="partName" label="紧固部位" width="180" />
          <el-table-column prop="accumulatedDowntime" label="保养时间间隔" />
          <el-table-column prop="economicLifetimeThreshold" label="预警间隔" />
          <el-table-column prop="currentLifetime" label="当前运行时间" />
          <el-table-column prop="residualLifetime" label="距离下次保养" />
          <el-table-column prop="lasteMaintenanceTime" label="最后一次保养时间" width="200" />
        </el-table>
      </div>
    </div>
    <div class="bottom-container" v-show="isShowSteps">
      <div class="step-container">
        <el-steps :active="currentRecordStep">
          <el-step title="开始保养" description="保养前准备工作" />
          <el-step title="创建设备变更流程" description="从 MES 系统中，创建一个设备变更工单" />
          <el-step title="设备停机维护部件" description="设备停机，ME 开始对设备进行保养维护" />
          <el-step title="重置设备运行时间" description="保养维修完成后，需要重置 PLC 的运行时间" />
          <el-step
            title="维护完成校验部件"
            description="检查维护过程当中的涉及到的各个部件是否达到运行指标"
          />
          <el-step title="保养完成" />
        </el-steps>
      </div>
      <div class="group-button">
        <el-button
          @click="startMaintaining(currentPartId)"
          :disabled="isUnderMaintenance"
          style="width: 88px; margin-right: 88px"
          type="primary"
          >开始维护</el-button
        >
        <el-button
          @click="revertStep(currentPartId)"
          :disabled="notRevertStep"
          style="width: 88px; margin-right: 88px"
          type="primary"
          >上一步</el-button
        >
        <el-text style="font-size: 16px; color: black; font-weight: bold"
          >{{ currentPartName }}-{{ maintenanceStatus }}</el-text
        >
        <el-button
          @click="nextStep(currentPartId)"
          :disabled="notNextStep"
          style="width: 88px; margin-left: 88px"
          type="primary"
          >下一步</el-button
        >
        <el-button
          @click="cancelMaintaining(currentPartId)"
          :disabled="isRuning"
          style="width: 88px; margin-left: 88px"
          type="danger"
          >终止维护</el-button
        >
      </div>
    </div>
    <el-dialog v-model="isShowCheckListDialog" title="校验清单列表" width="800">
      <el-table :data="checkedItemList">
        <el-table-column property="description" label="校验项描述" />
        <el-table-column property="result" label="校验结果" />
        <el-table-column fixed="right" label="操作" width="120">
          <template #default="scope">
            <el-button
              @click="onPassClick(scope.row)"
              :disabled="scope.row.isPassed"
              link
              type="primary"
              size="small"
              >通过</el-button
            >
            <el-button
              @click="onFailClick(scope.row)"
              :disabled="!scope.row.isPassed"
              link
              type="primary"
              size="small"
              >撤销</el-button
            >
          </template>
        </el-table-column>
      </el-table>
    </el-dialog>
    <div style="position: absolute; left: 8px; top: 63px">
      <el-button @click="onBack" type="primary" plain>返回上一级</el-button>
    </div>
  </div>
</template>

<style lang="scss" scoped>
.main-container {
  padding: 8px;
  background-color: rgba(241, 236, 236, 0.877);
  min-height: 100%;

  .content-container {
    display: flex;
    justify-content: center;
    align-items: center;

    .device-card {
      box-shadow: 0px 0px 4px black;
      border-radius: 8px;
      padding: 8px;
      background-color: lightblue;
      width: 316px;
      height: 490px;

      .card-header {
        margin-bottom: 8px;
        color: black;
        span {
          font-weight: bold;
        }

        display: flex;
        justify-content: space-between;
      }

      .card-body {
        display: flex;
        justify-content: center;
        align-items: center;
      }

      .card-footer {
        margin-top: 8px;
        color: black;
        > div > span {
          font-weight: bold;
        }

        .space-between {
          display: flex;
          justify-content: space-between;
          align-items: center;
        }
      }
    }

    .table-container {
      :deep(.first-table-header-cell-class-name) {
        background-color: #00c86e;
        color: black;
      }

      :deep(.second-table-header-cell-class-name) {
        background-color: #409eff;
        color: black;
      }
      :deep(.third-table-header-cell-class-name) {
        background-color: #ff2841;
        color: black;
      }
    }
  }

  .bottom-container {
    .step-container {
      display: flex;
      justify-content: center;
      margin-top: 16px;
    }

    .group-button {
      margin-top: 8px;
      display: flex;
      justify-content: center;
    }
  }
}
</style>